#include "System.h"
#include <Math.h>
#include "..\CGraphics\CGraphics.h"

#define ENDMARK		"@end"
#define NODESMARK	"@nodes"
#define EDGESMARK	"@edges"
#define NODEMARK	"@@"

void DestroyAll()
		{DestroyNodeList(&NODELIST); DestroyEdgeList(&EDGELIST); DestroyTabelMhs(&TABELMHS); DestroyTabelMK(&TABELMK); DestroyTabelPMK(&TABELPMK);}

		
void ParseLoadCommand(Reader R) {
	if(R.nArgument < 2) {
		StartPrintMsg(); printf("ERROR : Tidak ada input nama file");
	}
	else {
		if(LoadFile(R.argument[1])) {
			SOURCEFILE = R.argument[1];
			StartPrintMsg(); SetColor(FGI); printf("Load file %s berhasil",R.argument[1].s);
		}
		else {
			StartPrintMsg(); SetColor(FYI); printf("Load file %s tidak sempurna",R.argument[1].s);
		}
	}
}
	
bool LoadFile(string filename) {
	DestroyAll();

	StartPrintProcess(); SetColor(FWI); printf("Loading file %s ...",filename.s);
	char fname[50];
	sprintf(fname,"%s.in",filename.s);
	FILE *f = fopen(fname,"r");
	if(f==NULL) {
		ContinuePrintProcess(); SetColor(FRI); printf("File tidak eksis");
		return false; // EARLY RETURN
	}
	
	bool retval = true;
	
	ReadArguments(f);
	while(!IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) && !mesinkarend) {
		if(IsStringEqual(CReader.argument[0],CharToString(NODESMARK))) retval = LoadNodes(f) && retval;
		else if(IsStringEqual(CReader.argument[0],CharToString(EDGESMARK))) retval = LoadEdges(f) && retval;
		else {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s tidak dikenali",CReader.argument[0].s);
			retval = false;

			ReadArguments(f);				
			
			while(!IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) && !mesinkarend && 
					!IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) && !IsStringEqual(CReader.argument[0],CharToString(EDGESMARK))) 
			{
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" SKIPPED");

				ReadArguments(f);				
			}
		}
		// ReadArguments(f);
	}
	
	if(!IsStringEqual(CReader.argument[0],CharToString(ENDMARK))) {
		ContinuePrintProcess(); SetColor(FRI); printf("%s tidak ditemukan", ENDMARK);
		retval = false;
	}
	
	retval = FinalizeTablePMK() && retval;
	retval = FinalizeEdges() && retval;
	
	fclose(f);
	
	ContinuePrintProcess(); SetColor(FCI); printf("Load selesai");
	return retval;
}

bool LoadNodes(FILE *f) {
	ContinuePrintProcess(); SetColor(FWI); printf("Load nodes ... ");
	bool retval = true;
	// ambil jumlah node yang akan di load. verifikasi.
	if(CReader.nArgument!=2) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Argument count mismatch");
		retval = false;
	}
	else if(!IsStringFloat(CReader.argument[1])) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan angka",CReader.argument[1].s);
		retval = false;
	}
	else {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK",CReader.argument[1].s);
		ReadArguments(f);
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		
		while(!end) {
			if(IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK))) {
				if(LoadSingleNode(f)) {
					retval = retval && true;
					// *node_count += 1;
				}
				else retval = false;
			}
			else {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= deklarasi node tidak valid",CReader.argument[2].s);
				retval = false;
				
				ReadArguments(f); // continue reading
			}
			// ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		} 
	}
	
	if(!retval) {
		// skip sampe ketemu node, edge, baru
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		while(!end) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s", out.s); SetColor(FWI); printf(" SKIPPED ");
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		} 
	}
	
	return retval;
}

bool LoadSingleNode(FILE *f) {
	ContinuePrintProcess(); SetColor(FWI); printf("Load single node ... ");
	bool retval = true;
	
	// Load single node, error handling kalo jumlah argumen mismatch, ga ada @@, 4 param akhir bukan float, nama node udah ada
	if(CReader.nArgument!=7) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Argument count mismatch");
		retval = false;
		
		ReadArguments(f);
	}
	else if(!IsStringFloat(CReader.argument[3]) || !IsStringFloat(CReader.argument[4]) || !IsStringFloat(CReader.argument[5]) || !IsStringFloat(CReader.argument[6])) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Bukan angka");
		retval = false;
		
		ReadArguments(f);
	}
	else if(SearchNodeByName(&NODELIST,DeleteSubString(CReader.argument[0],0,2))!=NULL) {
		string name = DeleteSubString(CReader.argument[0],0,2);
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s sudah ada",name.s);
		retval = false;
		
		ReadArguments(f);
	}
	else {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
		nodeAddress N = AllocateNode(
							DeleteSubString(CReader.argument[0],0,2),				// Nama
							fabs(StringToFloat(CReader.argument[3])),				// Retrieve
							fabs(StringToFloat(CReader.argument[4])),				// Update
							fabs(StringToFloat(CReader.argument[5])),				// Insert
							fabs(StringToFloat(CReader.argument[6])),				// Delete
							IsStringEqual(CReader.argument[2],CharToString("Y")),	// Client
							IsStringEqual(CReader.argument[1],CharToString("Y")) 	// Server 
						);
						
		AddNode(&NODELIST,N);
		ReadArguments(f);
		
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) ||
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		while(!end) {
			string namatabel = NAMATABELMHS;
			string namatabel2 = NAMATABELMK;
			string namatabel3 = NAMATABELPMK;
			if(IsStringEqual(CReader.argument[0],namatabel)) retval = LoadTableMhs(f,N) && retval;
			else if(IsStringEqual(CReader.argument[0],namatabel2)) retval = LoadTableMK(f,N) && retval;
			else if(IsStringEqual(CReader.argument[0],namatabel3)) retval = LoadTablePMK(f,N) && retval;
			else {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan nama tabel",CReader.argument[0].s);
				retval = false;
						
				ReadArguments(f);
			}
			// ReadArguments(f);
			
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		}
	}
	
		
	if(!retval) {
	// skip sampe ketemu node, edge, baru
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		while(!end) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s", out.s); SetColor(FWI); printf(" SKIPPED ");
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
		} 
	}
		
	return retval;
}

bool LoadTableMhs(FILE *f, nodeAddress N) {
	bool retval = true;
	string out = ArgumentsToString(CReader);
	ContinuePrintProcess(); SetColor(FW); printf("%s",out.s);
	if(!HAS_SERVER(N)) {
		SetColor(FWI); printf(" <= %s tidak punya server", NODENAME(N).s);
		retval = false;
	}
	else {
		SetColor(FGI); printf(" OK");
	}
	
	
	string namatabel = NAMATABELMHS;
	string namatabel2 = NAMATABELMK;
	string namatabel3 = NAMATABELPMK;
	ReadArguments(f);
	// ngecek apakah node punya server
	if(retval) {
		HAS_TMHS(N) = true;
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			if(CReader.nArgument!=4 && CReader.nArgument!=6) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= argument count mismatch");
				retval = false;
			}
			else if(!IsStringDate(CReader.argument[2])) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan tanggal",CReader.argument[2].s);
				retval = false;
			}
			else {
				AddressMhs M = SearchRecordMhsByNIM(CReader.argument[0],&TABELMHS);
				if(M!=NULL) {
					if(SearchOwnerByNode(&OWNERLIST(M),N)!=NULL) {
						string out = ArgumentsToString(CReader);
						ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Record tereplikasi di tempat yang sama");
						retval = false;
					}
					else {
						string out = ArgumentsToString(CReader);
						ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
						AddOwnerToRecordMhs(M,AllocateOwnerList(N));
					}
				}
				else {
					string out = ArgumentsToString(CReader);
					ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
					M = AllocateRecordMhs(CReader.argument[0],CReader.argument[1],StringToDate(CReader.argument[2]),CReader.argument[3]);
					AddRecordMhs(M,&TABELMHS);
					AddOwnerToRecordMhs(M,AllocateOwnerList(N));
				}
			}
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);		
		}
	}
	else {
		// TODO : skip sampe kondisi end di atas
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" SKIPPED");
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		}
	}
	return retval;
}

bool LoadTableMK(FILE *f, nodeAddress N) {
	bool retval = true;
	string out = ArgumentsToString(CReader);
	ContinuePrintProcess(); SetColor(FW); printf("%s",out.s);
	if(!HAS_SERVER(N)) {
		SetColor(FWI); printf(" <= %s tidak punya server", NODENAME(N).s);
		retval = false;
	}
	else {
		SetColor(FGI); printf(" OK");
	}
	string namatabel = NAMATABELMHS;
	string namatabel2 = NAMATABELMK;
	string namatabel3 = NAMATABELPMK;
	
	ReadArguments(f);
	if(retval) {
		HAS_TMK(N) = true;
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			if(CReader.nArgument!=4) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= argument count mismatch");
				retval = false;
			}
			else if(!IsStringFloat(CReader.argument[2])) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan angka",CReader.argument[2].s);
				retval = false;
			}
			else {
				AddressMK M = SearchRecordMKByKode(CReader.argument[0],&TABELMK);
				if(M!=NULL) {
					if(SearchOwnerByNode(&OWNERLIST(M),N)!=NULL) {
						string out = ArgumentsToString(CReader);
						ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Record tereplikasi di tempat yang sama");
						retval = false;
					}
					else {
						string out = ArgumentsToString(CReader);
						ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
						AddOwnerToRecordMK(M,AllocateOwnerList(N));
					}
				}
				else {
					string out = ArgumentsToString(CReader);
					ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
					M = AllocateRecordMK(CReader.argument[0],CReader.argument[1],fabs(StringToInt(CReader.argument[2])),CReader.argument[3]);
					AddRecordMK(M,&TABELMK);
					AddOwnerToRecordMK(M,AllocateOwnerList(N));
				}
			}
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);		
		}
	}
	else {
		// TODO : skip sampe kondisi end di atas
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" SKIPPED");
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		}
	}
	return retval;
}

bool LoadTablePMK(FILE *f, nodeAddress N) {
	bool retval = true;
	string out = ArgumentsToString(CReader);
	ContinuePrintProcess(); SetColor(FW); printf("%s",out.s);
	if(!HAS_SERVER(N)) {
		SetColor(FWI); printf(" <= %s tidak punya server",NODENAME(N).s);
		retval = false;
	}
	else {
		SetColor(FGI); printf(" OK");
	}
	
	string namatabel = NAMATABELMHS;
	string namatabel2 = NAMATABELMK;
	string namatabel3 = NAMATABELPMK;
	ReadArguments(f);
	// ngecek apakah node punya server
	if(retval) {
		HAS_TPMK(N) = true;
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			if(CReader.nArgument!=5) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= argument count mismatch");
			retval = false;
			}
			else if(!IsStringFloat(CReader.argument[2])) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan angka",CReader.argument[2].s);
				retval = false;
			}
			else if(!IsStringThnAkademik(CReader.argument[3])) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan ThnAkademik",CReader.argument[3].s);
				retval = false;
			}
			else if(!IsStringABCDE(CReader.argument[4])) {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= %s bukan nilai yang valid",CReader.argument[4].s);
				retval = false;
			}
			else {
				string out = ArgumentsToString(CReader);
				ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
				
				AddressMhs M1 = AllocateRecordMhs(CReader.argument[0], CharToString("T"), MakeTanggal(1,1,1) ,CharToString("J")); // DUMMY
				AddressMK  M2 = AllocateRecordMK(CReader.argument[1], CharToString("T"),1,CharToString("J")); // DUMMY
				AddressPMK M = AllocateRecordPMK(	M1,M2,fabs(StringToInt(CReader.argument[2])),
													StringToThnAkademik(CReader.argument[3]),StringToChar(UpperCase(CReader.argument[4]))[0]);
				AddRecordPMK(M,&TABELPMK);
				AddOwnerToRecordPMK(M,AllocateOwnerList(N));
			}
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);		
		}
	}
	else {
		// TODO : skip sampe kondisi end di atas
		bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		
		while(!end) {
			string out = ArgumentsToString(CReader);
			ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" SKIPPED");
			ReadArguments(f);
			end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || IsStringEqual(SubString(CReader.argument[0],0,2),CharToString(NODEMARK)) || 
					IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK)) || 
					IsStringEqual(CReader.argument[0],namatabel) || IsStringEqual(CReader.argument[0],namatabel2) || IsStringEqual(CReader.argument[0],namatabel3);
		}
	}
	return retval;
}
	
bool LoadEdges(FILE *f) {
	ContinuePrintProcess(); SetColor(FWI); printf("Load Edges ... ");	
	
	bool retval = true;
	string out = ArgumentsToString(CReader);
	ContinuePrintProcess(); SetColor(FW); printf("%s",out.s);

	
	// verifikasi.
	if(CReader.nArgument!=2) {
		SetColor(FWI); printf(" <= argument count mismatch");
		retval = false;
	}
	else if(!IsStringFloat(CReader.argument[1])) {
		SetColor(FWI); printf(" <= %s bukan angka",CReader.argument[1].s);
		retval = false;
	}
	else {
		SetColor(FGI); printf(" OK");
	}
	
	ReadArguments(f);
	bool end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
				IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
	
	while(!end) {
		retval = retval && LoadSingleEdge(f);
		ReadArguments(f);
		end = 	mesinkarend || IsStringEqual(CReader.argument[0],CharToString(ENDMARK)) || 
				IsStringEqual(CReader.argument[0],CharToString(NODESMARK)) || IsStringEqual(CReader.argument[0],CharToString(EDGESMARK));
	}
	
	return retval;
}	

bool LoadSingleEdge(FILE *f) {
	bool retval = true;
	if(CReader.nArgument!=4) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= argument count mismatch");
		retval = false;
	}
	else if(!IsStringFloat(CReader.argument[2]) || !IsStringFloat(CReader.argument[3])) {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FWI); printf(" <= Bukan angka");
		retval = false;		
	}
	else {
		string out = ArgumentsToString(CReader);
		ContinuePrintProcess(); SetColor(FW); printf("%s",out.s); SetColor(FGI); printf(" OK");
		nodeAddress N1 = AllocateNode(CReader.argument[0],1,1,1,1,true,true); // DUMMY
		nodeAddress N2 = AllocateNode(CReader.argument[1],1,1,1,1,true,true); // DUMMY
		edgeAddress E = AllocateEdge(N1,N2,fabs(StringToFloat(CReader.argument[2])),fabs(StringToFloat(CReader.argument[3])));
		
		AddEdge(&EDGELIST,E);
	}
	
	return retval;
}

bool FinalizeTablePMK() {
	// memperbaiki tabel PMK
	ContinuePrintProcess(); SetColor(FWI); printf("Finalizing Tabel PengambilanMK ...");
	
	bool retval = true;
	
	if(ISLINKEDLISTEMPTY(TABELPMK)) return true;
	
	AddressPMK M;
	AddressPMK next;
	TabelPMK TPMK = CreateEmptyTabelPMK();
	// ganti dummy dengan record asli
	TRAVERSETOEND2(M,FIRST(TABELPMK)) {
		AddressMhs Mhs = SearchRecordMhsByNIM(NIM(MHS(M)),&TABELMHS);
		AddressMK MK = SearchRecordMKByKode(KODEMK(MK(M)),&TABELMK);
		bool del = false;
		if(Mhs==NULL) {
			ContinuePrintProcess(); SetColor(FY); printf("Mahasiswa dengan NIM %s tidak ditemukan",NIM(MHS(M)).s);
			del = true;
			retval = false;
		}
		if(MK==NULL) {
			ContinuePrintProcess(); SetColor(FY); printf("MataKuliah dengan Kode %s tidak ditemukan",KODEMK(MK(M)).s);
			del = true;
			retval = false;
		}
		DeallocateRecordMhs(MHS(M));
		DeallocateRecordMK(MK(M));
		if(del) {
			// delete PMK
			DestroyRecordPMK(M,&TABELPMK);
		}
		else {
			ChangeRecordPMKContent(M,Mhs,MK,SEMESTER(M),TAHUN(M),NILAI(M));
		}
	}
	// memastikan TabelPMK unik
	while(!ISLINKEDLISTEMPTY(TABELPMK)) {
		M = FIRST(TABELPMK);
		RemoveRecordPMK(M,&TABELPMK);
		AddressPMK tobedeleted = SearchRecordPMKByKey(MHS(M),MK(M),SEMESTER(M),TAHUN(M),&TABELPMK);
		while(tobedeleted!=NULL) {
			if(SearchOwnerByNode(&OWNERLIST(M),NODE(FIRST(OWNERLIST(tobedeleted))))!=NULL)
				AddOwnerToRecordPMK(M,AllocateOwnerList(NODE(FIRST(OWNERLIST(tobedeleted)))));
			else {
				ContinuePrintProcess(); SetColor(FY); printf("Suatu Record PengambilanMK tereplikasi ganda di %s",NODENAME(NODE(FIRST(OWNERLIST(tobedeleted)))).s);
				retval = false;
			}
			DestroyRecordPMK(tobedeleted,&TABELPMK);
			tobedeleted = SearchRecordPMKByKey(MHS(M),MK(M),SEMESTER(M),TAHUN(M),&TABELPMK);
		}
		
		AddRecordPMK(M,&TPMK);
	}
	
	TABELPMK = TPMK;
	
	// update IPK JmlSKS Mahasiswa
	AddressMhs Mhs;
	TRAVERSETOEND2(Mhs,FIRST(TABELMHS))
		UpdateIPKdanJmlSKSRecordMhs(Mhs,&TABELPMK);
	
	return retval;
} 

bool FinalizeEdges() {
	// memperbaiki kesalahan edges
	bool retval = true;
	ContinuePrintProcess(); SetColor(FWI); printf("Finalizing Edges ...");
	
	if(ISLINKEDLISTEMPTY(EDGELIST)) return true;
	
	edgeAddress E;
	edgeAddress next;
	for(E=FIRST(EDGELIST),next=NEXT(E);E!=NULL;E=next,next=((E==NULL) ? NULL : NEXT(E))) {
		nodeAddress N1 = SearchNodeByName(&NODELIST,NODENAME(GetA(E)));
		nodeAddress N2 = SearchNodeByName(&NODELIST,NODENAME(GetB(E)));
		
		if(N1==NULL) {
			ContinuePrintProcess(); SetColor(FY); printf("Node %s tidak terdefinisi",NODENAME(GetA(E)).s);
			DestroyEdge(&EDGELIST,E);
			retval = false;
		}
		else if(N2==NULL) {
			ContinuePrintProcess(); SetColor(FY); printf("Node %s tidak terdefinisi",NODENAME(GetB(E)).s);
			DestroyEdge(&EDGELIST,E);
			retval = false;
		}
		else {
			DeallocateNode(GetA(E));
			DeallocateNode(GetB(E));
			
			GetA(E) = N1;
			GetB(E) = N2;
		}
	}
	return retval;
}


